/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.Deflater;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.model.Filter;
import org.zhiqim.kernel.model.Filters;

/**
 * JAR包相关工具类
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Jars")
public class Jars
{
    /** 通过JarEntry获取类名 */
    public static String getClassName(JarEntry jarEntry)
    {//格式如:org/zhiqim/kernel/Global.class
     //1.去掉.class的后缀，2.把/替换成 .
        String className = jarEntry.getName();
        className = Strings.trimRight(className, ".class");
        className = Strings.replaceAll(className, "/", ".");
        return className;
    }
    
    /** 查询JAR包中过滤列表 */
    public static List<JarEntry> queryFilterList(JarFile file, Filter filter)
    {
        List<JarEntry> list = new ArrayList<JarEntry>();
        queryFilterList(list, file, filter);
        return list;
    }
    
    /** 查询JAR包中匹配到数据放入该列表 */
    public static void queryFilterList(List<JarEntry> entryList, JarFile file, Filter filter)
    {
        Asserts.notNull(entryList);
        Enumeration<JarEntry> enumeration = file.entries(); 
        while (enumeration.hasMoreElements()) 
        { 
            JarEntry entry = enumeration.nextElement();
            String name = entry.getName(); 
            if (filter.accept(name))
                entryList.add(entry);
        }
    }
    
    /** 查询JAR包中后缀匹配到数据放入该列表  */
    public static void queryEndsWithList(List<JarEntry> entryList, JarFile file, String endsWith)
    {
        queryFilterList(entryList, file, new Filters.EndsWithName(endsWith));
    }
    
    /** jar打包压缩文件 */
    public static void jar(String fileDirPath, String jarExportPath) throws Exception
    {
        Asserts.notEmpty(fileDirPath, "文件目录路径");
        Asserts.notEmpty(jarExportPath, "JAR导出路径");
        
        File fileDir = new File(fileDirPath);
        Asserts.as(fileDir.exists()?null:"文件目录路径不存在");

        //转化为/方式的绝对路径
        String fileDirCanonicalPath = Files.toLinuxPath(fileDir.getCanonicalPath());
        
        FileOutputStream fos = new FileOutputStream(jarExportPath);
        JarOutputStream jos = new JarOutputStream(fos);
        jos.setLevel(Deflater.BEST_COMPRESSION);
        
        List<File> fileList = new ArrayList<>();
        Files.queryFileList(fileList, fileDir, 0);
        
        for (File file : fileList)
        {
            String name = Files.toLinuxPath(file.getCanonicalPath());
            if (file.isDirectory())
                name = name.substring(fileDirCanonicalPath.length()+1) + "/";
            else
                name = name.substring(fileDirCanonicalPath.length()+1);
            
            JarEntry ze = new JarEntry(name);
            ze.setSize(file.length());
            ze.setTime(file.lastModified());
            jos.putNextEntry(ze);
            
            if (ze.isDirectory())
            {//目录
                jos.closeEntry();
            }
            else
            {//文件
                try (InputStream is = new FileInputStream(file))
                {
                    Streams.putBytes(is, jos);
                }
                jos.closeEntry();
            }
        }

        jos.close();
    }
}
